package textileGraphGeneration

import (
	"gitee.com/kaylee595/textileGraphGeneration/colorx"
	"image"
	"image/color"
	"image/draw"
)

type TextileGraphBuilder struct {
	// patternImg 图案图片
	patternImg image.Image
}

// NewTextileGraphBuilder 创建纺织图生成器
// patternImg 图案图片
func NewTextileGraphBuilder(patternImg image.Image) *TextileGraphBuilder {
	return &TextileGraphBuilder{
		patternImg: patternImg,
	}
}

// Depression 凹陷
type Depression struct {
	ColorKey color.RGBA
	UintImg  image.Image
}

// OverlayFun
// x, y 表示当前绘制的坐标
// c 该坐标的颜色
// img 绘制的图形
type OverlayFun func(x, y int, c color.Color, img *image.RGBA)

type TextileGraphBuilderOption struct {
	unitImg            image.Image
	offset             image.Point
	bottomColor        color.Color
	depression         *Depression
	overlayWithUintImg OverlayFun
	overlay            OverlayFun
}

// GenerateNewUnitImg 生成新的单位图
func (t *TextileGraphBuilderOption) GenerateNewUnitImg(x, y int, c color.Color) (result *image.RGBA) {
	r, g, b, a := colorx.ColorToUint8(c)
	if t.depression != nil &&
		t.depression.ColorKey.R == r &&
		t.depression.ColorKey.G == g &&
		t.depression.ColorKey.B == b &&
		t.depression.ColorKey.A == a {
		// 凹陷图
		result = image.NewRGBA(t.depression.UintImg.Bounds())
		draw.Draw(result, result.Bounds(), t.depression.UintImg, image.Point{}, draw.Over)
	} else {
		// 单位图
		result = colorx.ChangeImgColor(t.unitImg, nil, c)
		// 单位图的叠加图
		if t.overlayWithUintImg != nil {
			t.overlayWithUintImg(x, y, c, result)
		}
	}
	// 全局叠加图
	if t.overlay != nil {
		t.overlay(x, y, c, result)
	}
	return
}

type Option func(option *TextileGraphBuilderOption)

func WithUnitImg(i image.Image) Option {
	return func(o *TextileGraphBuilderOption) {
		o.unitImg = i
	}
}

func WithOffset(x, y int) Option {
	return func(o *TextileGraphBuilderOption) {
		o.offset.X = x
		o.offset.Y = y
	}
}

func WithBottomColor(c color.Color) Option {
	return func(o *TextileGraphBuilderOption) {
		o.bottomColor = c
	}
}

// WithDepression 凹陷
func WithDepression(d *Depression) Option {
	return func(o *TextileGraphBuilderOption) {
		o.depression = d
	}
}

// WithOverlayWithUintImg 单位图的叠加图
func WithOverlayWithUintImg(f OverlayFun) Option {
	return func(o *TextileGraphBuilderOption) {
		o.overlayWithUintImg = f
	}
}

// WithOverlay 全局的叠加图
func WithOverlay(f OverlayFun) Option {
	return func(o *TextileGraphBuilderOption) {
		o.overlay = f
	}
}

// Build 构建
func (b *TextileGraphBuilder) Build(options ...Option) image.Image {
	// 创建选项
	opt := new(TextileGraphBuilderOption)
	for _, option := range options {
		option(opt)
	}
	// 计算画布大小
	bitImgWidth, bitImgHeight := b.patternImg.Bounds().Max.X, b.patternImg.Bounds().Max.Y
	unitImgWidth, unitImgHeight := opt.unitImg.Bounds().Max.X, opt.unitImg.Bounds().Max.Y
	resultImageWidth := (unitImgWidth + opt.offset.X) * bitImgWidth
	resultImageHeight := (unitImgHeight + opt.offset.Y) * bitImgHeight
	if resultImageWidth > 8000 || resultImageHeight > 8000 {
		return nil
	}
	// 创建画布
	resultImg := image.NewRGBA(image.Rect(0, 0,
		resultImageWidth,
		resultImageHeight,
	))
	// 绘制底色
	if opt.bottomColor != nil {
		for x := 0; x < resultImageWidth; x++ {
			for y := 0; y < resultImageHeight; y++ {
				resultImg.Set(x, y, opt.bottomColor)
			}
		}
	}
	// 绘画每个单位
	for y := 0; y < bitImgHeight; y++ {
		for x := 0; x < bitImgWidth; x++ {
			// 每个单位图的区域大小
			w, h := unitImgWidth+opt.offset.X, unitImgHeight+opt.offset.Y
			// 每个单位图的区域
			r := image.Rect(w*x, h*y, w*x+unitImgWidth, h*y+unitImgHeight)
			// 画什么图
			img := opt.GenerateNewUnitImg(x, y, b.patternImg.At(x, y))
			// 画它
			var i image.Image = img
			draw.Draw(resultImg, r, i, image.Point{}, draw.Over)
		}
	}
	return resultImg
}
